home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Your Choice 1
/
your choice.zip
/
your choice
/
PRGMMING
/
VISIONIX
/
VUARTU.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1993-12-29
|
40KB
|
2,059 lines
{
════════════════════════════════════════════════════════════════════════════
Visionix Serial Communictions Unit - 8250/16450/16550 UART (VUART)
Version 0.8
Copyright 1991,92,93 Visionix
ALL RIGHTS RESERVED
────────────────────────────────────────────────────────────────────────────
** revision history in reverse chronological order **
Initials Date Comment
──────── ──────── ────────────────────────────────────────────────────────
mep 11/15/93 First logged revision.
────────────────────────────────────────────────────────────────────────────
}
(*-
[TEXT]
<Overview>
This unit implements functions to interface with the PC/ATs 8250,
16450, or 16550 Univeral Asychronous Receiver/Transmitter, or UART
chip. The UART chip is the PCs interface to the RS-232 world.
Additionally, this unit impelements a function to interface the UART
functions into the VSERu device-indepednent serial unit. This function,
UartSerDriverProc, is a serial driver procedure for VDOSu serial channels.
UartSerDriverProc can be specified as the serial-driver for a serial
channel by calling VSerDriverNew and specifying UartSerDriverProc
as the serial driver procedure.
<Interface>
-*)
Unit VUartU;
Interface
Uses
VTypesu,
VSerlu,
DOS;
Procedure VUartBaudSet( BaudRate : LONGINT );
Function VUartBaudGet : LONGINT;
Function VUartInit( ComPort : BYTE;
BaudRate : LONGINT ): WORD;
Procedure VUartDeInit;
Procedure VUartDTROn;
Procedure VUartDTROff;
Function VUartIsTXReady : BOOLEAN;
Function VUartIsCarrier : BOOLEAN;
Function VUartIsRXReady : BOOLEAN;
Function VUartReadChar : CHAR;
Procedure VUartWriteChar( Ch : CHAR );
Procedure VUartOutFlush;
Procedure VUartOutPurge;
Procedure VUartInPurge;
Procedure VUartBreak( DelayMS : WORD );
Procedure VUartCtsRtsSet( ON : BOOLEAN );
Procedure UartSerDriverProc( SDP : PSerDriverPacket );
{────────────────────────────────────────────────────────────────────────────}
IMPLEMENTATION
Const
cUartClockFreq = 115200;
cMaxComPort = 7;
cInBuffSize = 8196;
cInBuffMax = 8195;
cUartInt = $14;
cIntMaskReg = $21; { 8259 interrupt mask register }
{----------------------------}
{ 8250/16450/16550 registers }
{----------------------------}
cUartTHR = $00; { }
cUartRBR = $00; { }
cUartIER = $01; { Interrupt Enable Register }
cUartIIR = $02; { Interrupt ID Register }
cUartFCR = $02; { 16550 FIFO control register }
cUartLCR = $03; { Line Control Register }
cUartMCR = $04; { Modem Control Register }
cUartLSR = $05; { Line Status Register }
cUartMSR = $06; { Modem Status Register }
{---------------------------------}
{ Interrupt Enable Register flags }
{---------------------------------}
cEnableRcvInt = $01; { enable receive interrupt }
cEnableXfrInt = $02; { enable transfer interrupt }
cEnableLSInt = $04; { enable line-status interrupt }
cEnableMSInt = $08; { enable modem-status interrupt}
{-----------------------------------}
{ Interrupt ID Register (IIR) Flags }
{-----------------------------------}
cIntPending = $01; { an interrupt is pending }
cIntIDMask = $02+$04; { interrupt ID mask }
cIntIDLookMSR = $00; { interrupt ID=look in MSR }
cIntIDXfer = $02; { interrupt ID=transfered data }
cIntIDRcv = $04; { interrupt ID=received data }
cIntFifoTimeout = $08; { 16550 FIFO timeout }
cFifoModeMask = $40+$80; { 16550 Mode Status Mask }
cFifoModeChar = $00; { 16550 Mode=char (emu 16450) }
cFifoModeDMA = $40; { 16550 Mode=type 3 DMA }
cFifoModeFifo = $80+$40; { 16550 Mode=FIFO enabled }
{-----------------------------------}
{ FIFO Control Register (FCR) Flags }
{-----------------------------------}
cFifoEnable = $01; { 16550 Fifo Enable flag }
cFifoRcvBuffReset = $02; { 16550 Reset Receive buffer }
cFifoXferBuffReset = $04; { 16550 Reset Transmit buffer }
cFifoFTSMask = $80+$40; { 16550 FIFO Trigger Size mask }
cFifoFTS1 = $00; { 16550 FIFO Trig Size=1 byte }
cFifoFTS4 = $40; { 16550 FIFO Trig Size=4 bytes}
cFifoFTS8 = $80; { 16550 FIFO Trig Size=8 bytes}
cFifoFTS14 = $80+$40; { 16550 FIFO Trig Size=14 bytes}
{-----------------------------------}
{ Line Control Register( LCR) Flags }
{-----------------------------------}
cDataBitsMask = $01+$02; { Data bits (wordsize) mask }
cDataBits5 = $00; { Data bits = 5 }
cDataBits6 = $01; { Data bits = 6 }
cDataBits7 = $02; { Data bits = 7 }
cDataBits8 = $01+$02; { Data bits = 8 }
cStopBits1 = $00; { Stop bits = 1 }
cStopBits2 = $04; { Stop bits = 2 }
cParityEnable = $08; { Enable parity }
cParityEven = $10; { even parity }
cStickyParity = $20; { sticky parity }
cBreakOn = $40; { turn break on }
cAccessDivLatch = $80; { access divisor latch }
{------------------------------------}
{ Modem Control Register (MCR) flags }
{------------------------------------}
cDTR = $01; { Data terminal ready }
cRTS = $02; { Ready to send }
cOut1 = $04; { Out 1 - not used in PCs }
cOut2 = $08; { Out 2 - }
cMasterEnableInts = $08; { master enables interrupts }
cLoop = $10; { Loop enable (for testing) }
{----------------------------------}
{ Line Status Register (LSR) Flags }
{----------------------------------}
cDataInRcvBuff = $01; { data in receive buffer }
cOverrunError = $02; { overrrun error }
cParityError = $04; { parity error }
cFramingError = $08; { framing error }
cIncomingBreak = $10; { incoming break detected }
cTHREmpty = $20; { Transmit holding reg is empty}
cTSREmpty = $40; { Transmit shift reg is empty}
cFIFORcvError = $80; { 16550 Fifo receive error }
{-----------------------------------}
{ Modem Status Register (MSR) Flags }
{-----------------------------------}
cdCTS = $01; { delta-clear to send }
cdDSR = $02; { delta-Data Set Ready }
cdRI = $04; { delta-Ring }
cdDCD = $08; { delta-Data Carrier Detect }
cCTS = $10; { Clear to send }
cDSR = $20; { Data Set Ready }
cRI = $40; { Ring Indicator }
cDCD = $80; { Data Carrier Detect }
Type
TPortSettings = RECORD
BasePort : WORD;
IRQ : BYTE;
END;
PPortSettings = ^TPortSettings;
TUartInBuffer = Array[0..cInBuffMax] of BYTE;
PUartInBuffer = ^TUartInBuffer;
Const
PortSettings : Array[0..cMaxComPort] of TPortSettings=
( (BasePort : $3F8; IRQ : 4),
(BasePort : $2F8; IRQ : 3),
(BasePort : $3E8; IRQ : 4),
(BasePort : $2E8; IRQ : 3),
(BasePort : $000; IRQ : 0),
(BasePort : $000; IRQ : 0),
(BasePort : $000; IRQ : 0),
(BasePort : $000; IRQ : 0) );
Var
ExitSave : POINTER;
OriginalVector : POINTER;
UartIsOpen : BOOLEAN;
Overflow : BOOLEAN;
Base : WORD; { current baseport }
IRQ : BYTE; { current IRQ }
Buffer : TUartInBuffer;
BufferHead : WORD;
BufferTail : WORD;
SaveIER : BYTE;
SaveMCR : BYTE;
SaveLCr : BYTE;
CtsRtsOn : Boolean;
{────────────────────────────────────────────────────────────────────────────}
(*-
[FUNCTION]
Procedure VUartBaudSet( BaudRate : LONGINT );
[PARAMETERS]
baudrate new baud rate to use
[RETURNS]
nothing.
[DESCRIPTION]
This function will set the baud rate of the UART to the specified
value.
THIS FUNCTION IS NOT YET IMPLEMENTED!
[SEE-ALSO]
[EXAMPLE]
VUartBaudSet( 19200 );
-*)
Procedure VUartBaudSet( BaudRate : LONGINT );
BEGIN
END;
{────────────────────────────────────────────────────────────────────────────}
(*-
[FUNCTION]
Function VUartBaudGet : LONGINT;
[PARAMETERS]
none.
[RETURNS]
current Baud rate of the UART.
[DESCRIPTION]
This function will get the current baud rate of the UART.
[SEE-ALSO]
[EXAMPLE]
WriteLn(' Baud Rate = ', VUartBaudGet );
-*)
Function VUartBaudGet : LONGINT;
Var
SaveLCR : WORD;
BRD : WORD;
BEGIN
{-------------------------------------}
{ get the line control register value }
{-------------------------------------}
SaveLCR := Port[ cUartLCR + Base ];
{----------------------------------}
{ set the access divsor latch flag }
{----------------------------------}
Port[ cUartLCR + Base ] := SaveLCR OR cAccessDivLatch;
{-------------------------------------------------------------}
{ The THR and IER regs are now the Baud Rate Divisor register }
{ so we get the baud rate divisor }
{-------------------------------------------------------------}
TCastWord( BRD ).LowByte := Port[ cUartTHR + Base ];
TCastWord( BRD ).HighByte := Port[ cUartIER + Base ];
{--------------------------------------------------------------}
{ clear the access divisor latch / set LCR back to what it was }
{--------------------------------------------------------------}
Port[ cUartLCR + Base ] := SaveLCR;
{-------------------------------------------------}
{ divide the input clock by the baud rate divisor }
{ to get the baud rate }
{-------------------------------------------------}
VUartBaudGet := cUartClockFreq DIV BRD;
END;
{────────────────────────────────────────────────────────────────────────────}
(*-
[FUNCTION]
Function VUartLSRGet : BYTE;
[PARAMETERS]
None.
[RETURNS]
Line Status Register.
[DESCRIPTION]
This function will get the line-status register of the UART.
Line status register flags
--------------------------
cDataInRcvBuff = $01; { data in receive buffer }
cOverrunError = $02; { overrrun error }
cParityError = $04; { parity error }
cFramingError = $08; { framing error }
cIncomingBreak = $10; { incoming break detected }
cTHREmpty = $20; { Transmit holding reg is empty}
cTSREmpty = $40; { Transmit shift reg is empty}
cFIFORcvError = $80; { 16550 Fifo receive error }
[SEE-ALSO]
[EXAMPLE]
If (VUartLSRGet AND cParityError)>0 Then
WriteLn('Parity error!')
Else
WriteLn('No parity error.');
-*)
Function VUartLSRGet : BYTE;
BEGIN
VUartLSRGet := (Port[ Base+cUartLSR ]);
END;
{────────────────────────────────────────────────────────────────────────────}
(*-
[FUNCTION]
Function VUartMSRGet : BYTE;
[PARAMETERS]
None.
[RETURNS]
Modem Status Register.
[DESCRIPTION]
This function will get the modem-status register of the UART.
Modem status register flags
---------------------------
cdCTS = $01; { delta-clear to send }
cdDSR = $02; { delta-Data Set Ready }
cdRI = $04; { delta-Ring }
cdDCD = $08; { delta-Data Carrier Detect }
cCTS = $10; { Clear to send }
cDSR = $20; { Data Set Ready }
cRI = $40; { Ring Indicator }
cDCD = $80; { Data Carrier Detect }
[SEE-ALSO]
[EXAMPLE]
If (VUartMSRGet AND cCTS)>0 Then
WriteLn('Clear to send!')
Else
WriteLn('cant send yet....');
-*)
Function VUartMSRGet : BYTE;
BEGIN
VUartMSRGet := (Port[ Base+cUartMSR ]);
END;
{────────────────────────────────────────────────────────────────────────────}
(*-
[FUNCTION]
Function VUartLCRGet : BYTE;
[PARAMETERS]
None.
[RETURNS]
Line control Register.
[DESCRIPTION]
This function will get the line-control register of the UART.
Line-Control register flags
---------------------------
cDataBitsMask = $01+$02; { Data bits (wordsize) mask }
cDataBits5 = $00; { Data bits = 5 }
cDataBits6 = $01; { Data bits = 6 }
cDataBits7 = $02; { Data bits = 7 }
cDataBits8 = $01+$02; { Data bits = 8 }
cStopBits1 = $00; { Stop bits = 1 }
cStopBits2 = $04; { Stop bits = 2 }
cParityEnable = $08; { Enable parity }
cParityEven = $10; { even parity }
cStickyParity = $20; { sticky parity }
cBreakOn = $40; { turn break on }
cAccessDivLatch = $80; { access divisor latch }
[SEE-ALSO]
[EXAMPLE]
-*)
Function VUartLCRGet : BYTE;
BEGIN
VUartLCRGet := (Port[ Base+cUartLCR ]);
END;
{────────────────────────────────────────────────────────────────────────────}
(*-
[FUNCTION]
Function VUartMCRGet : BYTE;
[PARAMETERS]
None.
[RETURNS]
Line control Register.
[DESCRIPTION]
This function will get the modem-control register of the UART.
modem-Control register flags
----------------------------
cDTR = $01; { Data terminal ready }
cRTS = $02; { Ready to send }
cOut1 = $04; { Out 1 - not used in PCs }
cOut2 = $08; { Out 2 - }
cMasterEnableInts = $08; { master enables interrupts }
cLoop = $10; { Loop enable (for testing) }
[SEE-ALSO]
[EXAMPLE]
-*)
Function VUartMCRGet : BYTE;
BEGIN
VUartMCRGet := (Port[ Base+cUartMCR ]);
END;
{────────────────────────────────────────────────────────────────────────────}
(*-
[FUNCTION]
Function VUartIsCarrier : BOOLEAN;
[PARAMETERS]
None.
[RETURNS]
TRUE if a carrier is present,
FALSE if a carrier is NOT present.
[DESCRIPTION]
This function will return TRUE if a data carrier is present.
[SEE-ALSO]
[EXAMPLE]
-*)
Function VUartIsCarrier : BOOLEAN;
BEGIN
VUartISCarrier := (Port[ CUartMSR + Base ] AND cDCD)>0;
END;
{────────────────────────────────────────────────────────────────────────────}
(*-
[FUNCTION]
Procedure CommIsr; Interrupt;
[PARAMETERS]
None.
[RETURNS]
Nothing.
[DESCRIPTION]
This procedure is the VUartU s internal interrupt service routine.
It should NOT be called externally. This interrupt is called any time the
UART receives a character.
[SEE-ALSO]
[EXAMPLE]
-*)
Procedure CommIsr; Interrupt;
BEGIN
ASM
{ get the incoming character from the UART }
{ and put it into our incoming char buffer }
@@GetTheChar:
STI
MOV DX, Base
IN AL, DX
MOV BX, BufferHead
MOV byte PTR Buffer[BX], AL
INC BX
{ check to see if we are at the end of the buffer }
@@CheckAtEnd:
CMP BX, cInBuffMax
JLE @@CheckOver
XOR BX, BX
{ check to see if an overflow occurred (head=tail) }
@@CheckOver:
CMP BX, BufferTail
JNE @@CheckNextChar
MOV Overflow,1
JMP @@AllDone
{ check to see if more characters are waiting }
@@CheckNextchar:
MOV Bufferhead, BX
ADD DX,5
IN AL,DX
AND AL, $01
CMP AL, $01
JE @@GetTheChar
{ clean up and leave }
@@AllDone:
CLI
MOV AL,20h
OUT 20h, AL
END;
END; { CommIsr }
{────────────────────────────────────────────────────────────────────────────}
(*-
[FUNCTION]
Procedure VUartClose;
[PARAMETERS]
None.
[RETURNS]
Nothing.
[DESCRIPTION]
This function is used internally.
[SEE-ALSO]
[EXAMPLE]
-*)
Procedure VUartClose;
BEGIN
If UartIsOpen Then
BEGIN
{ begin critical code }
ASM CLI; END;
{ turn off our int in the 8259 IRQ mask register }
Port[ cIntMaskReg ] := ( Port[ cIntMaskReg ] or (1 SHL IRQ) );
{ restore the saved UART registers }
Port[ Base + cUartIER ] := SaveIER;
Port[ Base + cUartMCR ] := SaveMCR;
Port[ Base + cUartLCR ] := SaveLCR;
{ restore the orignal interrupt vector }
SetIntVec( IRQ+8, OriginalVector );
{ end of critical code }
ASM STI; END;
UartIsOpen := FALSE;
END;
END;
{────────────────────────────────────────────────────────────────────────────}
(*-
[FUNCTION]
Function VUartOpen( ComPort : BYTE;
BaudRate : LONGINT ):BOOLEAN;
[PARAMETERS]
comport comport to open (1-4)
baudrate baudrate to use
[RETURNS]
TRUE if the open was successfull,
FALSE if the open was not.
[DESCRIPTION]
This function is used internally.
[SEE-ALSO]
[EXAMPLE]
-*)
Function VUartOpen( ComPort : BYTE;
BaudRate : LONGINT ):BOOLEAN;
Var
SaveIIR : BYTE;
Is16550 : BOOLEAN;
PortGood : BOOLEAN;
BEGIN
{ set the buffer head and tail to nada }
BufferHead := 0;
BufferTail := 0;
{ clear overflow and uartisopen flag }
Overflow := FALSE;
UartIsOpen := FALSE;
{ do we know the baseport for this com-port? }
If PortSettings[ Pred( ComPort ) ].BasePort <>0 Then
BEGIN
{ get out baseport and irq }
Base := PortSettings[ Pred( ComPort ) ].BasePort;
IRQ := PortSettings[ Pred( ComPort ) ].IRQ;
{ save various UART regs }
SaveIER := Port[ Base + cUartIER ];
SaveMCR := Port[ Base + cUartMCR ];
SaveLCR := Port[ Base + cUartLCR ];
{ check for the port }
Port[ Base+CUartLCR ] := $75;
PortGood := (Port[ Base + CUartLCR ]=$75);
{ set port to n,8,1 }
Port[ Base+cUartLCR ] := cDataBits8;
If PortGood Then
BEGIN
{ set the baud }
VUartBaudSet( BaudRate );
{ turn on master ints, and set RTS and DTR }
Port[ Base + CUartMCR ] := cMasterEnableInts + cRTS + cDTR;
{ save the interrupt ID register }
SaveIIR := Port[ Base + cUartIIR ];
{ try to enable the fifos }
Port[ Base + cUartIIR ] := 1;
{ did the Fifo mode status flags show up? }
Is16550 := ( ( Port[ Base + cUartIIR ] AND
cFifoModeMask ) = cFifoModeFifo );
{ if they didnt, set IIR back to what it was }
If Is16550=FALSE Then
Port[ Base + CUartIIR ] := SaveIIR;
{ save the original IRQ vector off }
GetIntVec( IRQ+8, OriginalVector );
{ setup our IRQ vector }
SetIntVec( IRQ+8, @CommIsr );
{ beginning of critical code }
ASM CLI; END;
{ enable our IRQ in the 8259 IRQ mask register }
Port[ cIntMaskReg ] := Port[ cIntMaskReg ] AND
( (1 SHL IRQ) XOR $FF );
{ enable the 8250s receive interrupt }
Port[ Base + cUartIER ] := cEnableRcvInt;
{ end or critical code }
ASM STI; END;
UartIsOpen := TRUE;
END; { if portthere }
END; { if we found a base port in the settings table }
VUartOpen := UartIsOpen;
END;
{────────────────────────────────────────────────────────────────────────────}
Procedure ExitUnit; Far;
BEGIN
VUartClose;
ExitProc := ExitSave;
END;
{────────────────────────────────────────────────────────────────────────────}
(*-
[FUNCTION]
Function VUartInit( ComPort : BYTE;
BaudRate : LONGINT ): WORD;
[PARAMETERS]
comport comport to open (1-4)
baudrate baudrate to use
[RETURNS]
TRUE if the open was successfull,
FALSE if the open was not.
[DESCRIPTION]
This function should be called before the other VUart functions are
used. "Comport" should be the comport (1-4) that you wish to use.
"baudrate" is the baud rate you would like the comport to be opened
at. This function initializes the UART and sets up the Vuart
interrupt service routine to service incoming characters.
[SEE-ALSO]
[EXAMPLE]
-*)
Function VUartInit( ComPort : BYTE;
BaudRate : LONGINT ): WORD;
BEGIN
If Not UartIsOpen Then
BEGIN
If VUartOpen( ComPort, BaudRate ) Then
VUartInit := 0
ELSE
VUartInit := 1;
END; { if not UartIsOpen }
END; { VUartInit }
{────────────────────────────────────────────────────────────────────────────}
(*-
[FUNCTION]
Function VUartIsRXReady : BOOLEAN;
[PARAMETERS]
None.
[RETURNS]
TRUE if characters are available to be read from the receive buffer,
FALSE if no characters are available.
[DESCRIPTION]
This function reports on the condition of the receiver buffer. It
will return TRUE if characters are available, and FALSE if characters
are not available.
[SEE-ALSO]
[EXAMPLE]
-*)
Function VUartIsRXReady : BOOLEAN;
BEGIN
VUartIsRXReady := (BufferHead<>BufferTail);
END;
{────────────────────────────────────────────────────────────────────────────}
(*-
[FUNCTION]
Procedure VUartDeInit;
[PARAMETERS]
None.
[RETURNS]
Nothing.
[DESCRIPTION]
This procedure should be called when your program is done with the
UART. This function disposes of any dynamically memory that was
allocated by VUartOpen and restores the UART back to the state
it was in when open called. This function also restores the
UARTS interrupt service routine back to what it previously was.
[SEE-ALSO]
[EXAMPLE]
-*)
Procedure VUartDeInit;
BEGIN
VUartClose;
END;
{────────────────────────────────────────────────────────────────────────────}
(*-
[FUNCTION]
Function VUartReadChar : CHAR;
[PARAMETERS]
None.
[RETURNS]
The new character.
[DESCRIPTION]
This function reads the next available character from the receive buffer.
If no characters are available, it waits until a character is received,
and then returns it.
[SEE-ALSO]
[EXAMPLE]
-*)
Function VUartReadChar : CHAR;
BEGIN
{ wait till something is in the buffer }
While BufferTail=BufferHead DO;
{ read a character }
VUartReadChar := char( Buffer[ BufferTail ] );
{ move the tail }
BufferTail := ( Succ( BufferTail ) MOD cInBuffSize );
END;
{────────────────────────────────────────────────────────────────────────────}
(*-
[FUNCTION]
Function VUartIsTXReady : BOOLEAN;
[PARAMETERS]
None.
[RETURNS]
TRUE if the UART is ready to write another character,
FALSE if it is not.
[DESCRIPTION]
This function returns TRUE if the UART is currently ready to send
out another character, and FALSE if it is not.
[SEE-ALSO]
[EXAMPLE]
-*)
Function VUartIsTXready : BOOLEAN;
Var
THR : BOOLEAN;
CTS : BOOLEAN;
Car : BOOLEAN;
BEGIN
{ check THR, CTS, and CAR }
THR := ( (Port[ Base+cUartLSR ] and cTHREmpty) >0 );
CTS := ( (Port[ Base+cUartMSR ] and cCTS ) >0 );
CAR := ( (Port[ Base+CUartMSR ] and cDCD ) >0 );
{ if cts/rts is on and their is a carrier ... }
If CtsRtsOn and CAR Then
VUartIsTXReady := THR AND CTS
ELSE
VUartIsTXReady := THR;
END;
{────────────────────────────────────────────────────────────────────────────}
(*-
[FUNCTION]
Procedure VUartWriteChar( Ch : CHAR );
[PARAMETERS]
ch character to write.
[RETURNS]
[DESCRIPTION]
This function writes a charcter to the UART. Before using this
function, you should first check to make sure the UART is ready to
send another character.
[SEE-ALSO]
[EXAMPLE]
-*)
Procedure VUartWriteChar( Ch : CHAR );
BEGIN
{ wait until output is ready }
While Not VUartIsTXReady DO;
{ send the char }
Port[ Base+cUartTHR ] := Byte(Ch);
END;
{────────────────────────────────────────────────────────────────────────────}
(*-
[FUNCTION]
Procedure VUartOutFlush;
[PARAMETERS]
[RETURNS]
[DESCRIPTION]
This function insures that any characters which are buffered
and have not yet been sent are sent.
[SEE-ALSO]
[EXAMPLE]
-*)
Procedure VUartOutFlush;
BEGIN
{ flush 16550 fifos }
END;
{────────────────────────────────────────────────────────────────────────────}
(*-
[FUNCTION]
Procedure VUartOutPurge;
[PARAMETERS]
[RETURNS]
[DESCRIPTION]
This function purges any characters which are in the transmit buffer.
Since UART currently does not implement a transmit buffer, this function
doesn't do anything.
[SEE-ALSO]
[EXAMPLE]
-*)
Procedure VUartOutPurge;
BEGIN
{ Purge 16550 fifos }
END;
{────────────────────────────────────────────────────────────────────────────}
(*-
[FUNCTION]
Procedure VUartInPurge;
[PARAMETERS]
[RETURNS]
[DESCRIPTION]
This function purges any characters that are in the receive buffer.
[SEE-ALSO]
[EXAMPLE]
-*)
Procedure VUartInPurge;
BEGIN
BufferHead := 0;
BufferTail := 0;
OverFlow := FALSE;
END;
{────────────────────────────────────────────────────────────────────────────}
(*-
[FUNCTION]
Procedure VUartBreak( DelayMS : WORD );
[PARAMETERS]
delayms count of milliseconds to break for.
[RETURNS]
[DESCRIPTION]
This function sends a break signal for the specified "delayMS".
[SEE-ALSO]
[EXAMPLE]
-*)
Procedure VUartBreak( DelayMS : WORD );
Var
LCR : BYTE;
BEGIN
{ get the current LCR }
LCR := Port[ Base+cUartLCR ];
{ put it back with BREAK ON set }
Port[ Base+cUartLCR ] := ( (LCR AND $7F) OR cBreakOn );
{ delay... }
{ Delay( DelayMS ); }
{ set LCR back to what it was }
Port[ Base+cUartLCR ] := LCR;
END;
{────────────────────────────────────────────────────────────────────────────}
(*-
[FUNCTION]
Procedure VUartDTROn;
[PARAMETERS]
[RETURNS]
[DESCRIPTION]
This function turns DTR (Data Terminal Ready) on.
[SEE-ALSO]
[EXAMPLE]
-*)
Procedure VUartDTROn;
BEGIN
Port[ Base+cUartMCR ] := cMasterEnableInts + cRTS + cDTR;
END;
{────────────────────────────────────────────────────────────────────────────}
Procedure VUartDTROff;
BEGIN
Port[ Base+cUartMCR ] := cMasterEnableInts + cRTS;
END;
{────────────────────────────────────────────────────────────────────────────}
Procedure VUartCtsRtsSet( ON : BOOLEAN );
BEGIN
CtsRtsOn := ON;
END;
{────────────────────────────────────────────────────────────────────────────}
Procedure VUartWriteBlock( Block : POINTER;
Count : WORD );
Var
Z : INTEGER;
BEGIN
For Z := 1 to Count Do
VUartWriteChar( PCharArray( Block )^[Z] );
END;
{────────────────────────────────────────────────────────────────────────────}
Procedure VUartReadBlock( Block : POINTER;
Count : WORD );
Var
Z : INTEGER;
BEGIN
For Z := 1 to Count Do
PCharArray( Block )^[Z] := VUartReadChar;
END;
{────────────────────────────────────────────────────────────────────────────}
Procedure UartSerDriverProc( SDP : PSerDriverPacket );
Type
TUartIData = RECORD
ComPort : BYTE; { Communications port }
BaudRate : LONGINT; { Bits per second rate }
Parity : CHAR; { Parity of hardware error checking }
DataBits : BYTE; { Number of data bits }
StopBits : BYTE; { Number of stop bits }
PortStat : WORD; { Condition of UART. LoByte=MSR,HiByte=LSR }
END;
PUartIdata = ^TUartIdata;
Var
IData : PUartIData;
BEGIN
IData := SDP^.IData;
If SDP^.Status = 0 Then
BEGIN
Case SDP^.Func of
{--------}
SDFDriverNew:
BEGIN
IF @SDP^.SerDriverProc = @UartSerDriverProc Then
BEGIN
New( IData );
FillChar( IData^, SizeOf( TUartIData), 0 );
{--------------------------}
{ build instance data here }
{--------------------------}
IData^.ComPort := Pred( SDP^.DriverInfo1 );
{--------------------------}
SDP^.IData := IData;
SDP^.Error := 0;
END;
END; { Case SDF_DriverNew }
{--------}
SDFDriverOff:
BEGIN
END;
{--------}
SDFDriverOn:
BEGIN
END;
{--------}
SDFDriverDispose:
BEGIN
{--------------------------------}
{ Resolve any instance data here }
{--------------------------------}
{---------------------------}
{ Dispose all instance data }
{---------------------------}
If SDP^.IData <> NIL Then
BEGIN
Dispose( SDP^.IData );
SDP^.IData := NIL;
END;
END;
{--------}
SDFActivate:
BEGIN
SDP^.Error := 0;
If VUartInit( IData^.ComPort,
SDP^.CommParam^.BaudRate )=0 Then
BEGIN
SDP^.Error := 0;
END
ELSE
BEGIN
SDP^.Error := $FFFF0000;
END;
END;
{--------}
SDFDeActivate:
BEGIN
VUartDeInit;
SDP^.Error := 0;
END;
{--------}
SDFSetCommParam:
BEGIN
(*
IData^.BaudRate := SDP^.CommParam^.BaudRate;
IData^.Parity := SDP^.CommParam^.Parity;
IData^.DataBits := SDP^.CommParam^.DataBits;
IData^.StopBits := SDP^.CommParam^.StopBits;
*)
SDP^.Error := 0;
END;
{--------}
SDFGetCommParam:
BEGIN
SDP^.CommParam^.BaudRate := VUartBaudGet;
SDP^.CommParam^.Parity := 'N';
SDP^.CommParam^.DataBits := 8;
SDP^.CommParam^.StopBits := 1;
SDP^.Error := 0;
END;
{--------}
SDFGetFlowConType:
BEGIN
SDP^.Error := 0;
END;
{--------}
SDFSetFlowConType:
BEGIN
SDP^.Error := $FFFF0000;
END;
{--------}
SDFTurnSendOnOff:
BEGIN
SDP^.Error := $FFFF0000;
END;
{--------}
SDFTurnReceiveOnOff:
BEGIN
SDP^.Error := $FFFF0000;
END;
{--------}
sdfGetFlowConChars:
BEGIN
SDP^.Error := $FFFF0000;
END;
{--------}
sdfSetFlowConChars:
BEGIN
SDP^.Error := $FFFF0000;
END;
{--------}
{--------}
{--------}
sdfGetLineControl:
BEGIN
SDP^.Val := VUartLCRGet;
SDP^.Error := 0;
END;
{--------}
sdfGetLineStatus:
BEGIN
SDP^.Val := VUartLSRGet;
SDP^.Error := 0;
END;
{--------}
sdfGetModemControl:
BEGIN
SDP^.Val := VUartMCRGet;
SDP^.Error := 0;
END;
{--------}
sdfGetModemStatus:
BEGIN
SDP^.Val := VUartMSRGet;
SDP^.Error := 0;
END;
{--------}
sdfGetBothStatus:
BEGIN
{ msr in lower, lsr in higher }
SDP^.Status := (Word(VUartLSRGet) SHL 8) +
( (VuartMSRGet) );
SDP^.Status := ( SDP^.Status AND ($FFFF-$0100-$2000) );
If VUartIsRXReady Then
Inc( SDP^.Status, $0100 );
If VuartIsTXReady Then
Inc( SDP^.Status, $2000 );
(*
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
1 2 4 5 1 3 6 1 2 5 1 2 4 8
6 2 4 2 5 1 0 0 0 1
8 6 2 2 4 9 9
4 8 6 2
VUartIsRXReady := (BufferHead<>BufferTail);
sbf_LSRRcvReady = 8; { Received data ready }
$0100
vuartistxready
sbf_LSRXhReady = 13; { Transmit hold register empty }
$2000
*)
END;
{--------}
{--------}
{--------}
{--------}
{--------}
SDFDTROnOff:
BEGIN
If SDP^.OnOff Then
VUartDTROn
ELSE
VUartDTROff;
SDP^.Error := 0;
END;
{--------}
SDFBreakOnOff:
BEGIN
SDP^.Error := 0;
END;
{--------}
SDFRTSOnOff:
BEGIN
(*
If SDP^.OnOff Then
VUartRTSOn
ELSE
VUartRTSOff;
*)
SDP^.Error := 0;
END;
{--------}
{--------}
{--------}
SDFFlushOutBuff:
BEGIN
VUartOutFlush;
SDP^.Error := 0;
END;
{--------}
SDFPurgeOutBuff:
BEGIN
VUartOutPurge;
SDP^.Error := 0;
END;
{--------}
SDFPurgeInBuff:
BEGIN
VUartInPurge;
SDP^.Error := 0;
END;
{--------}
sdfGetOutBuffInfo:
BEGIN
{ we can only hold 1 outgoing char }
SDP^.BuffInfo.Size := 1;
{ is the output ready? }
If VUartisTXReady Then
BEGIN
SDP^.BuffInfo.Used := 0;
SDP^.BuffInfo.Free := 1;
END
ELSE
BEGIN
SDP^.BuffInfo.Used := 1;
SDP^.BuffInfo.Free := 0;
END;
SDP^.BuffInfo.Changeable := FALSE;
SDP^.Error := 0;
END;
{--------}
sdfSetOutBuffInfo:
BEGIN
SDP^.Error := $FFFF0000;
END;
{--------}
sdfGetInBuffInfo:
BEGIN
SDP^.BuffInfo.Size := SizeOf( Buffer );
ASM CLI; END;
If BufferTail<=BufferHead Then
BEGIN
SDP^.BuffInfo.Used := BufferHead-BufferTail;
SDP^.BuffInfo.Free := SizeOf( Buffer ) - SDP^.BuffInfo.Used;
END
ELSE
BEGIN
SDP^.BuffInfo.Used := (Sizeof( Buffer ) - Succ(BufferTail)) +
(Succ(BufferHead) );
SDP^.BuffInfo.Free := SizeOf( Buffer ) - SDP^.BuffInfo.Used;
END;
ASM STI; END;
SDP^.BuffInfo.Changeable := FALSE;
SDP^.Error := 0;
END;
{--------}
sdfSetInBuffInfo:
BEGIN
SDP^.Error := $FFFF0000;
END;
{--------}
{--------}
{--------}
SDFEventProcNew:
BEGIN
END;
{--------}
SDFEventProcOff:
BEGIN
END;
{--------}
SDFEventProcOn:
BEGIN
END;
{--------}
SDFEventProcDispose:
BEGIN
END;
{--------}
sdfEventProcMaskSet:
BEGIN
SDP^.Error := $FFFF0000;
END;
{--------}
{--------}
{--------}
SDFWriteCh:
BEGIN
VUartWriteChar( SDP^.CH );
SDP^.Error := 0;
END;
{--------}
SDFWriteBlock:
BEGIN
VUartWriteBlock( SDP^.Buf,
SDP^.Count );
SDP^.Error := 0;
END;
{--------}
SDFReadCh:
BEGIN
SDP^.Error := 0;
SDP^.CH := VUartReadChar;
END;
{--------}
SDFReadBlock:
BEGIN
VUartReadBlock( SDP^.Buf,
SDP^.Count );
SDP^.Error := 0;
END;
{--------}
sdfPeekCh:
BEGIN
SDP^.Error := $FFFF0000;
END;
{--------}
End;
END;
END;
{────────────────────────────────────────────────────────────────────────────}
{────────────────────────────────────────────────────────────────────────────}
{────────────────────────────────────────────────────────────────────────────}
BEGIN
ExitSave := ExitProc;
ExitProc := @ExitUnit;
UartIsOpen := FALSE;
Overflow := FALSE;
CtsRtsOn := TRUE;
END.